package com.gwd.task.services.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.gwd.task.entity.ProjectEntity;
import com.gwd.task.entity.ProjectNumEntity;
import com.gwd.task.exception.DataException;
import com.gwd.task.model.*;
import com.gwd.task.repository.ProjectRepository;
import com.gwd.task.services.*;
import com.gwd.task.untils.ListPredicate;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author zhiyongming
 * @date 2020/11/19 14:42
 */
@Service
public class ProjectServerImpl implements ProjectServer {

    @Resource
    private ProjectRepository projectRepository;
    @Resource
    private GroupServer groupServer;
    @Resource
    private ProjectNumServer projectNumServer;
    @Resource
    private ProjectModuleServer projectModuleServer;

    @Override
    public List<ProjectDTO> findByGroup(Long groupId) {
        ProjectEntity entity = new ProjectEntity();
        entity.setGroupId(groupId);
        entity.setStatus(null);

        List<ProjectDTO> list = projectRepository.findAll(Example.of(entity)).stream().map(ProjectDTO::new).collect(Collectors.toList());
        List<GroupDTO> groupDTOList = groupServer.findAll();
        list.forEach(e -> groupDTOList.forEach(s -> {
            if (e.getGroupId().equals(s.getGroupId())) {
                e.setGroupName(s.getGroupName());
            }
        }));

        List<ProjectModuleDTO> moduleDTOList =
                projectModuleServer.findByProjectIdList(list.stream().map(ProjectDTO::getProjectId).collect(Collectors.toList()));

        //匹配模块
        list.forEach(e-> moduleDTOList.forEach(m -> {
            if (m.getProjectId().equals(e.getProjectId())) {
                e.addModule(m);
            }
        }));

        //匹配当前最大编号
        List<ProjectNumEntity> numList =
                projectNumServer.findByProjectIdList(list.stream().map(ProjectDTO::getProjectId).collect(Collectors.toList()));
        list.forEach(e -> numList.forEach(num -> {
            if (num.getProjectId().equals(e.getProjectId())) {
                e.setPeNum(num.getP());
                e.setTestNum(num.getT());
                e.setDevNum(num.getD());
            }
        }));

        return list;
    }

    @Override
    public List<ProjectDTO> findAll() {
        return projectRepository.findAll().stream().map(ProjectDTO::new).collect(Collectors.toList());
    }

    @Override
    public void save(ProjectDTO dto, List<ProjectModuleDTO> moduleList) {
        ProjectEntity save;
        if (dto.getProjectId()!=null) {
            Optional<ProjectEntity> t = projectRepository.findById(dto.getProjectId());
            if (!t.isPresent()) {
                throw new DataException("项目id:" + dto.getProjectId() + "不存在。");
            }
            int have = projectRepository.countByGroupIdAndProjectNameAndProjectIdNot(dto.getGroupId(), dto.getProjectName(), dto.getProjectId());
            if (have!=0) {
                throw new DataException("项目名称:" + dto.getProjectName() + "已存在。");
            }
            save = t.get();
        } else {
            int have = projectRepository.countByGroupIdAndProjectName(dto.getGroupId(), dto.getProjectName());
            if (have!=0) {
                throw new DataException("项目名称:" + dto.getProjectName() + "已存在。");
            }
            save = new ProjectEntity();
        }
        BeanUtil.copyProperties(dto, save, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        /*
         * 1: 跟新项目表
         * 2: 跟新项目对应的自动编号表
         */
        ProjectEntity s = projectRepository.save(save);
        projectNumServer.saveByProject(s);

    }

    @Override
    public void saveModules(Long projectId, Long groupId, List<ProjectModuleDTO> list) {
        projectModuleServer.saveV2(projectId, groupId, list);
    }

    @Override
    public void active(Long projectId) {
        projectRepository.findById(projectId).ifPresent(entity -> {
            entity.setStatus(0);
            projectRepository.save(entity);
        });
    }

    @Override
    public void remove(Long projectId) {
        projectRepository.findById(projectId).ifPresent(entity -> {
            entity.setStatus(1);
            projectRepository.save(entity);
        });
    }

    @Override
    public PageUtils findByPage(ProjectDTO dto, PageUtils pageUtils) {
        Page<ProjectEntity> projectEntities = projectRepository.findAll((Specification<ProjectEntity>)(root, query, cb) ->
                        ListPredicate.of(root, query, cb)
                                .equal("groupId", dto.getGroupId())
                                .like("projectName", dto.getProjectName())
                                .finish().getRestriction(),
                pageUtils.convert());

        pageUtils.convert(projectEntities);

        List<GroupDTO> groupDTOList = groupServer.findAll();

        List<ProjectDTO> dtoList = projectEntities.getContent().stream().map(ProjectDTO::new).collect(Collectors.toList());

        List<ProjectModuleDTO> moduleDTOList =
            projectModuleServer.findByProjectIdList(dtoList.stream().map(ProjectDTO::getProjectId).collect(Collectors.toList()));

        //匹配组别名称
        dtoList.forEach(e-> groupDTOList.forEach(d -> {
            if (e.getGroupId().equals(d.getGroupId())) {
                e.setGroupName(d.getGroupName());
            }
        }));

        //匹配模块
        dtoList.forEach(e-> moduleDTOList.forEach(m -> {
            if (m.getProjectId().equals(e.getProjectId())) {
                e.addModule(m);
            }
        }));

        pageUtils.setContent(dtoList);

        return pageUtils;
    }

    @Override
    public ProjectDTO findById(Long projectId) {
        Optional<ProjectEntity> entity = projectRepository.findById(projectId);
        return entity.map(ProjectDTO::new).orElse(null);
    }
}
